前言
當初開始這一個系列想說有三十天的份量可以寫,應該可以將所有內容寫完。
沒想到默默的只剩3天的Quota
既然我們已經完整的把
- Data Replication - Consensus Problem
- Data Partitioning - Distributed Hash Table
兩個很重要的部分介紹完,剩下的篇幅也不多,就拉高到最上層介紹一下當今火紅的雲端平台Kubernetes之設計吧。
Kubernetes
現在說到K8s應該是無人不知無人不曉,想當初碩一第一個任務就是在OpenStack(IaaS)上面使用Magum部署K8s,那時K8s還是一個網路上找不太到資料,Docker Swarm與K8s還在爭奪話語權的時候。
今天我們就從最簡單的例子開始,從頭了解Kubenretes運作原理吧。
Deployment 怎麼被部署到Kubernetes之上的?
Deployment是大家開始學K8s第一個實例,就是創建一個deployment yaml file,在裡面可以設定
- Container使用的Image
- Pod(一組Container)的數量
- 掛載的Volumes
- 一些額外的服務保證,比方說RestartPolicy...等
然後K8s就會幫你維護這些Container的生命週期與數量。究竟這是怎麼辦到的呢?
步驟
K8s主要分成兩個元件
- Master:
- API-Server: 為一個提供RestAPI的Server,負責接收Client送來的請求
- etcd: 分散式Key-Value Store,K8s儲存各式Data的元件,比方說目前創建的Pod其Spec與Status
- Scheduler: 調度Pod到Nodes上
- 各式Controller: 維護相對應的物件之生命週期
- Node(以前叫做 Minion,應該很多人不知道 xD):
- Kubelet: 回報該node的健康狀況
- Proxy: 負責Pod對外網路連線
- 首先Client透過API傳送創建一個Deployment的請求給API-Server
- K8s將該Deployment的Spec存進etcd中,儲存的格式為
(Key="namespace/name", Data="Spec+Status...")
- 各式的Controller可以利用HTTP1.1的Watch協定,去訂閱相關Rest Object的事件,比方說Add/Update/Delete,都會從API-Server發出讓Controller接收到
- Deployment Controller接收到Add事件後,會取得該Deployment的Spec,查看
- 他需要多少的Pods
- Pods的Spec是什麼
- 目前K8s中有多少Pods已經建立了
接著在以Client身份發起請求創建Pod給API-Server
- 此時etcd又儲存了被創建的Pod之Spec。而Scheduler作為另一個Controller,他訂閱的是沒有綁定Node的Pod之事件,因此會收到事件通知。並且根據目前的系統資源配置狀況,幫它調度到一個Node身上,而發起Update該Pod請求給API-Server,進而更新etcd裡面該Pod之Spec。
- 而K8s Node中的Kubelet作為另一個Controller,訂閱的是綁定到自身Pod的事件,因此他也會收到事件通知,並從中取得Pod Spec,根據此訊息實際創建Pod,並發起請求給API-Server更新該Pod。
- 從上面簡單的例子可以看到其實K8s的每一個元件幾乎都是一個個Controller,執行一個Infinite Loop。不斷監聽相關物件的事件,並比對現實的情況與Spec上的描述,利用發起請求給API-Server去讓K8s的實際情況符合Spec上的描述。
最基本的例子就是維護Deployment上面使用者指定的Pod Replica數量,一有Pod失效,Controller就可以比較數量少了一個,再次發起Create Pod請求給API-Server去維護數量。
總結
今天我們用一個很簡單的例子介紹K8s的運作原理,可以發現相較於傳統的分散式系統採用Message Queue或是用RPC來通訊。
K8s內部的元件反而是更偏向Event Trigger的,每一個元件都是利用HTTP Watch機制來訂閱有興趣的物件之事件,進而維護整個系統的狀態符合Spec的狀態。
是以維護狀態為核心思想來運作,最大的好處就是每一個Controller可以說是無狀態的,狀態是儲存在etcd那邊
- Controller接收到事件
- 現場取得Spec與K8s系統狀態
- 比較過後利用發起請求的方式給API-Server嘗試讓狀態吻合
這樣的設計機制使得K8s
- 每一個元件的相依性非常低,也就是說系統可以非常穩定,單一的Controller失效不會導致系統失效,
- 且因為Controller是無狀態的,所以直接重啟該Controller,系統也不會有任何問題
- 而且只要確保事件或是物件不會被重複處理(這可以用etcd的revision與客製化的Queue達到),更可以讓系統的scalibility更強大。
- 客製化的Controller成為可能,因為只要跟著其Design Pattern即可。
這樣的設計也使得雖然Docker Swarm較為簡單,效能也比較好。
仍然是Kubernetes勝出的原因,系統的穩定且恢復的能力也很強,最重要的是很容易客製化Controller與客製化Plugin。
明天我們就會進一步介紹Controller內部的設計,讓大家瞭解怎麼寫一個Controller。